package com.auto.service;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.RandomStringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.auto.entity.Art;
import com.auto.entity.Task;
import com.auto.entity.User;
import com.auto.pojo.Command;
import com.auto.rep.TaskRep;
import com.auto.rep.UserRep;
import com.auto.util.BeanUtil;
import com.auto.util.LOG;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

@Service
public class TaskExecutor {
	@Autowired
	private TaskRep taskRep;
	@Autowired
	private UserRep userRep;

	public static By getTarget(Command command) {
		if (command.getTargetMethod().equals("link")) {
			return By.linkText(command.getTargetValue());
		} else if (command.getTargetMethod().equals("id")) {
			return By.id(command.getTargetValue());
		}
		return null;
	}

	private List<Command> getCommand(Task task) {
		List<Command> cmds = Lists.newArrayList();
		Document doc = Jsoup.parse(task.getContent());
		Elements trs = doc.select("tbody").select("tr");
		for (int i = 0; i < trs.size(); ++i) {
			Elements tds = trs.get(i).select("td");
			Command cmd = new Command();
			cmd.setName(tds.get(0).text());
			String[] target = tds.get(1).text().split("=");
			cmd.setTargetMethod(target[0]);
			if (target.length > 1) {
				cmd.setTargetValue(target[1]);
			}
			cmd.setValue(tds.get(2).text());
			cmds.add(cmd);
		}
		return cmds;

	}

	private String getBaseUrl(Task task) {
		Document doc = Jsoup.parse(task.getContent());
		Elements ele = doc.select("link");
		return ele.get(0).attr("href");
	}
	public void execute(Task task) {
		String baseUrl = getBaseUrl(task);
		List<Command> cmds = getCommand(task);
		List<Art> arts = task.getArts();

		while (task.getNumberNow() < task.getNumber()) {
			LOG.info("执行任务{},第{}次", task.getName(), task.getNumberNow());
			WebDriver driver = new FirefoxDriver();
			driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
			User user = null;
			Art art = null;
			Map<String, String> map = Maps.newHashMap();
			for (Command command : cmds) {
				if (command.getName().equals("clickAndWait")) {
					WebElement we = driver.findElement(getTarget(command));
					we.click();
				} else if (command.getName().equals("type")) {
					WebElement we = driver.findElement(getTarget(command));
					we.clear();
					if (command.getValue().startsWith("$user.")) {
						if (user == null) {
							user = genUser();
							user.setSite(task.getSite());
							userRep.save(user);
							map.putAll(BeanUtil.convert(user, Map.class));
						}
					} else if (command.getValue().startsWith("#user.")) {
						if (user == null) {
							user = userRep.findOne(1L);
							map.putAll(BeanUtil.convert(user, Map.class));
						}
					} else if (command.getValue().startsWith("#art.")) {
						if (art == null) {
							art = arts.get(task.getNumberNow() / arts.size());
							map.putAll(BeanUtil.convert(art, Map.class));
						}
					}

					int index = command.getValue().indexOf(".");
					if (index > 0) {
						we.sendKeys(map
								.get(command.getValue().substring(index)));
					} else {
						we.sendKeys(map.get(command.getValue()));
					}

				} else if (command.getName().equals("open")) {
					driver.get(baseUrl + command.getTargetMethod());
				}
			}
			task.setNumberNow(task.getNumberNow() + 1);
			taskRep.save(task);
			driver.quit();
		}
		task.setFlag(1);
		taskRep.save(task);

	}

	public static User genUser() {
		User user = new User();
		user.setName(RandomStringUtils.random(6, "abcdefghijklmnopqrst"));
		user.setEmail(user.getName() + "@163.com");
		user.setPassword(RandomStringUtils
				.random(8, "abcdefghijklmn0123456789"));
		return user;
	}
}
